package com.mxpio.erp.equipment.controller;

import cn.hutool.core.date.DateUtil;
import com.mxpio.erp.common.enums.CommonEnums;
import com.mxpio.erp.common.enums.EquipmentEnums;
import com.mxpio.erp.common.equipment.entity.EquipmentUpkeepTask;
import com.mxpio.erp.common.equipment.entity.EquipmentUpkeepTaskEvaluate;
import com.mxpio.erp.common.equipment.entity.EquipmentUpkeepTaskPickupLine;
import com.mxpio.erp.common.equipment.service.EquipmentUpkeepTaskService;
import com.mxpio.erp.common.vo.OrderExcuteVo;
import com.mxpioframework.common.exception.MBootException;
import com.mxpioframework.common.vo.Result;
import com.mxpioframework.jpa.query.Criteria;
import com.mxpioframework.jpa.query.Operator;
import com.mxpioframework.jpa.query.SimpleCriterion;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.*;

import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;


@Tag(name = "EquipmentUpkeepTaskController", description = "保养任务")
@RestController
@RequestMapping("/erp/equipment/upkeep/task/")
public class EquipmentUpkeepTaskController {

    @Autowired
    private EquipmentUpkeepTaskService equipmentUpkeepTaskService;

    @GetMapping("list")
    @Operation(summary = "保养任务列表", description = "获取保养任务列表（无分页）", method = "GET")
    public Result<List<EquipmentUpkeepTask>> list(@Parameter(description = "查询参数") Criteria criteria) throws UnsupportedEncodingException {
        List<EquipmentUpkeepTask> list = equipmentUpkeepTaskService.list(EquipmentUpkeepTask.class, criteria);
        return Result.OK(list);
    }

    @GetMapping("page")
    @Operation(summary = "保养任务列表", description = "获取保养任务列表（分页）", method = "GET")
    public Result<Page<EquipmentUpkeepTask>> page(@Parameter(description = "查询参数") Criteria criteria, @Parameter(description = "每页条数") Integer pageSize, @Parameter(description = "页号") Integer pageNo) throws UnsupportedEncodingException {
        Pageable page = PageRequest.of(pageNo - 1, pageSize);
        List<Object> criterions = criteria.getCriterions();
        Boolean sevenDaysPastQuery = false;
        if (!criterions.isEmpty()){
            Iterator<Object> iterator = criterions.iterator();
            while(iterator.hasNext()){
                Object next = iterator.next();
                if (next instanceof SimpleCriterion){
                    SimpleCriterion simpleCriterion = (SimpleCriterion)next;
                    if (StringUtils.equals(simpleCriterion.getFieldName(),"sevenDaysPastQuery")){
                        sevenDaysPastQuery = true;
                        iterator.remove();
                        break;
                    }
                }
            }
        }
        if (sevenDaysPastQuery){
            Iterator<Object> iterator = criterions.iterator();
            while(iterator.hasNext()){
                Object next = iterator.next();
                if (next instanceof SimpleCriterion){
                    SimpleCriterion simpleCriterion = (SimpleCriterion)next;
                    if (StringUtils.equals(simpleCriterion.getFieldName(),"createTime")){
                        iterator.remove();
                    }
                }
            }
            String today = DateUtil.formatDate(new Date());
            criteria.addCriterion("planStartTime",Operator.LE,DateUtil.parseDateTime(today+" "+"23:59:59"));
            criteria.addCriterion("planStartTime",Operator.GT, DateUtils.addDays(DateUtil.parseDateTime(today+" "+"00:00:00"),-6));
        }
        Page<EquipmentUpkeepTask> pageResult = equipmentUpkeepTaskService.listPage(EquipmentUpkeepTask.class, page, criteria);
        return Result.OK(pageResult);
    }

    /**
     *  保养任务列表-当前登录用户协助列表
     * @param criteria
     * @param pageSize
     * @param pageNo
     * @return
     */
    @GetMapping("page/userAssistance")
    @Operation(summary = "保养任务列表-用户协助列表", description = "获取保养任务列表-用户协助列表（分页）", method = "GET")
    public Result<Page<EquipmentUpkeepTask>> userAssistedTickets(@Parameter(description = "查询参数") Criteria criteria,@Parameter(description = "每页条数") Integer pageSize, @Parameter(description = "页号") Integer pageNo){
        Pageable page = PageRequest.of(pageNo - 1, pageSize);
        Page<EquipmentUpkeepTask> pageResult = equipmentUpkeepTaskService.userAssistedTickets(criteria, page);
        return Result.OK(pageResult);
    }

    @GetMapping("queryExecutingList")
    @Operation(summary = "保养任务列表-保养中列表查询", description = "获取保养任务列表-保养中列表查询", method = "GET")
    public Result<List<EquipmentUpkeepTask>> list() {
        List<EquipmentUpkeepTask> list = equipmentUpkeepTaskService.queryExecutingList();
        return Result.OK(list);
    }

    @GetMapping("list/{id}")
    @Operation(summary = "根据ID获取保养任务列表", description = "根据ID获取保养任务列表", method = "GET")
    public Result<EquipmentUpkeepTask> getById(@PathVariable(name = "id", required = true) String id) {
        EquipmentUpkeepTask equipmentUpkeepTask = equipmentUpkeepTaskService.getById(EquipmentUpkeepTask.class, id);
        return Result.OK(equipmentUpkeepTask);
    }

    @RequestMapping("add")
    @Operation(summary = "保存保养任务", description = "保存保养任务")
    public Result<EquipmentUpkeepTask> add(@RequestBody EquipmentUpkeepTask equipmentUpkeepTask) {
        try {
            if (equipmentUpkeepTask.getIsAutoRelease()==Integer.parseInt(CommonEnums.YesNo.YES.getCode())
                    &&equipmentUpkeepTask.getAdvanceTime()==null){//自动释放
                return Result.error("自动释放时需要维护提前下达期");
            }
            equipmentUpkeepTaskService.saveTask(equipmentUpkeepTask);
        } catch (MBootException e) {
            return Result.error(e.getMessage());
        }
        return Result.OK(equipmentUpkeepTask);
    }

    @PutMapping("edit")
    @Operation(summary = "编辑保养任务", description = "编辑保养任务", method = "PUT")
    public Result<EquipmentUpkeepTask> edit(@RequestBody EquipmentUpkeepTask equipmentUpkeepTask) {
        try {
            if (equipmentUpkeepTask.getIsAutoRelease()==Integer.parseInt(CommonEnums.YesNo.YES.getCode())
                    &&equipmentUpkeepTask.getAdvanceTime()==null){//自动释放
                return Result.error("自动释放时需要维护提前下达期");
            }
            equipmentUpkeepTaskService.updateTask(equipmentUpkeepTask);
        } catch (MBootException e) {
            return Result.error(e.getMessage());
        }
        return Result.OK(equipmentUpkeepTask);
    }

    @PutMapping("admin/edit")
    @Operation(summary = "编辑保养任务-管理员", description = "编辑保养任务-管理员", method = "PUT")
    public Result<EquipmentUpkeepTask> adminEdit(@RequestBody EquipmentUpkeepTask equipmentUpkeepTask) {
        try {
            if (equipmentUpkeepTask.getIsAutoRelease()==Integer.parseInt(CommonEnums.YesNo.YES.getCode())
                    &&equipmentUpkeepTask.getAdvanceTime()==null){//自动释放
                return Result.error("自动释放时需要维护提前下达期");
            }
            equipmentUpkeepTaskService.adminUpdateTask(equipmentUpkeepTask);
        } catch (MBootException e) {
            return Result.error(e.getMessage());
        }
        return Result.OK(equipmentUpkeepTask);
    }

    @RequestMapping("release/{id}")
    @Operation(summary = "保存保养任务-下达", description = "保存保养任务-下达")
    public Result<?> release(@PathVariable(name = "id", required = true) String id) {
        equipmentUpkeepTaskService.release(id);
        return Result.OK("下达成功！");
    }

    @RequestMapping("dispatch/{id}/{executor}")
    @Operation(summary = "保存保养任务-派工", description = "保存保养任务-派工")
    public Result<?> dispatch(@PathVariable(name = "id", required = true) String id, @PathVariable(name = "executor", required = true) String executor) {
        equipmentUpkeepTaskService.dispatch(id, executor);
        return Result.OK("派工成功！");
    }

    @RequestMapping("grab/{id}")
    @Operation(summary = "保存保养任务-领单", description = "保存保养任务-领单")
    public Result<?> grab(@PathVariable(name = "id", required = true) String id) {
        equipmentUpkeepTaskService.grab(id);
        return Result.OK("领单成功！");
    }

    @RequestMapping("reSend/{id}/{executor}/{reason}")
    @Operation(summary = "保存保养任务-转单", description = "保存保养任务-转单")
    public Result<?> reSend(@PathVariable(name = "id", required = true) String id,
                            @PathVariable(name = "executor", required = true) String executor,
                            @PathVariable(name = "reason", required = true) String reason) {
        equipmentUpkeepTaskService.reSend(id, executor, reason);
        return Result.OK("转单成功！");
    }

    @RequestMapping("startExcut/{id}")
    @Operation(summary = "保存保养任务-开始执行", description = "保存保养任务-开始执行")
    public Result<?> startExcut(@PathVariable(name = "id", required = true) String id) {
        equipmentUpkeepTaskService.startExcut(id);
        return Result.OK("领单成功！");
    }

    @RequestMapping("excut")//finish接口
    @Operation(summary = "保存保养任务-结束保养", description = "保存保养任务-结束保养（finish接口）")
    public Result<?> excut(@RequestBody EquipmentUpkeepTask upkeepTask) {
        equipmentUpkeepTaskService.excut(upkeepTask);
        return Result.OK("执行成功！");
    }

    @RequestMapping("stop")
    @Operation(summary = "保存保养任务-暂停", description = "保存保养任务-暂停")
    public Result<?> stop(@RequestBody EquipmentUpkeepTask upkeepTask) {
        equipmentUpkeepTaskService.stopUpkeepById(upkeepTask.getReason(), upkeepTask.getBizNo());
        return Result.OK("暂停成功！");
    }

    @RequestMapping("end/{id}")
    @Operation(summary = "保存保养任务-暂停结束", description = "保存保养任务-暂停结束")
    public Result<?> endStop(@PathVariable(name = "id", required = true) String id) {
        equipmentUpkeepTaskService.endStop(id);
        return Result.OK("暂停结束成功！");
    }

    @DeleteMapping("remove/{bizNos}")
    @Operation(summary = "根据bizNos删除保养任务", description = "删除保养任务,多个bizNo用英文逗号分隔", method = "DELETE")
    public Result<String> remove(@PathVariable(name = "bizNos", required = true) String bizNos) {
        return equipmentUpkeepTaskService.deleteWithSub(Stream.of(bizNos.split(",")).collect(Collectors.toList()));
    }

    @RequestMapping (value = "/veto")
    @Operation(summary = "设备保养-否决", description = "设备保养-否决")
    public Result<?> veto(@RequestBody EquipmentUpkeepTask task) {
        return equipmentUpkeepTaskService.veto(task);
    }

    @RequestMapping (value = "/change",method = RequestMethod.POST)
    @Operation(summary = "设备保养执行状态-变更", description = "设备保养执行状态-变更")
    public Result<?> change(@RequestBody EquipmentUpkeepTask task) {
        return equipmentUpkeepTaskService.change(task);
    }

    //先完成，再提交
    @RequestMapping (value = "/submit")
    @Operation(summary = "设备保养-提交", description = "设备保养-提交")
    public Result<?> submit(@RequestBody EquipmentUpkeepTask task) {
        return equipmentUpkeepTaskService.submit(task);
    }

    @Operation(summary = "设备保养-验收", description = "设备保养-验收", method = "PUT")
    @PutMapping(value = "/check")
    public Result<?> check(@RequestBody EquipmentUpkeepTask task) {
        return equipmentUpkeepTaskService.check(task);
    }

    @Operation(summary = "设备保养-评价", description = "设备保养-评价", method = "PUT")
    @PutMapping(value = "/evaluate")
    public Result<?> evaluate(@RequestBody List<EquipmentUpkeepTaskEvaluate> evaluates) {
        return equipmentUpkeepTaskService.evaluate(evaluates);
    }

    @RequestMapping("excute/pickup/{bizNo}")
    @Operation(summary = "备件领料", description = "备件领料",method = "POST")
    public Result<List<EquipmentUpkeepTaskPickupLine>> excute(@PathVariable(name = "bizNo", required = true) String bizNo,@RequestBody OrderExcuteVo orderExcuteVo) {
        EquipmentUpkeepTask order = equipmentUpkeepTaskService.getById(EquipmentUpkeepTask.class, bizNo);
        /*if (order.getCloseStatus().equals(OrderStatusEnums.CloseStatus.CLOSED.getStatusCode())){
            return Result.error("关闭状态不能执行该操作");
        }*/
        int parseIntValue = Integer.parseInt(order.getOrderStatus());
        if (parseIntValue>=Integer.parseInt(EquipmentEnums.UpkeepStatus.REPORT.getCode())){
            return Result.error("已完成后不能执行该操作");
        }
        return equipmentUpkeepTaskService.executePickUp(order, orderExcuteVo.getLines());
    }

    @RequestMapping("excute/return/{bizNo}")
    @Operation(summary = "备件已领料退料", description = "备件已领料退料",method = "POST")
    public Result<Object> excuteReturn(@PathVariable(name = "bizNo", required = true) String bizNo,@RequestBody OrderExcuteVo orderExcuteVo) {
        EquipmentUpkeepTask order = equipmentUpkeepTaskService.getById(EquipmentUpkeepTask.class, bizNo);
        int parseIntValue = Integer.parseInt(order.getOrderStatus());
        if (parseIntValue>=Integer.parseInt(EquipmentEnums.UpkeepStatus.ZIPPED.getCode())){//归档之前均可以退料
            return Result.error("归档后不能执行该操作");
        }
        return equipmentUpkeepTaskService.executeReturn(order, orderExcuteVo.getLines());
    }
    @RequestMapping (value = "/shut")
    @Operation(summary = "设备保养-关闭（异常）", description = "设备保养-关闭（异常）")
    public Result<?> shut(@RequestBody EquipmentUpkeepTask task) {
        return equipmentUpkeepTaskService.shut(task);
    }

    @PutMapping("occupy/{bizNo}")
    @Operation(summary = "手动占用", description = "手动占用", method = "PUT")
    public Result<EquipmentUpkeepTask> occupy(@PathVariable(name = "bizNo", required = true) String bizNo) throws Exception {
        EquipmentUpkeepTask byId = equipmentUpkeepTaskService.getById(EquipmentUpkeepTask.class, bizNo);
        if (!byId.getOrderStatus().equals(EquipmentEnums.UpkeepStatus.START.getCode())){
            return Result.error("不在待下达状态, 不可占用");
        }
        if (!byId.getPmisHold().equals(EquipmentEnums.PmisHode.PENDINGPRODUCTION.getCode())){
            return Result.error("不在待排产状态, 不可占用");
        }
        return equipmentUpkeepTaskService.updateOccupy(byId);
    }

    @PutMapping("partOccupy")
    @Operation(summary = "根据占用时间批量占用", description = "根据占用时间批量占用", method = "PUT")
    public Result<EquipmentUpkeepTask> partOccupy(@RequestBody EquipmentUpkeepTask equipmentUpkeepTask) throws Exception {
        Criteria criteria = Criteria.create();
        criteria.addCriterion("planStartTime", Operator.GE,equipmentUpkeepTask.getPlanStartTime());
        criteria.addCriterion("planEndTime", Operator.LE,equipmentUpkeepTask.getPlanEndTime());
        criteria.addCriterion("pmisHold", Operator.EQ,EquipmentEnums.PmisHode.PENDINGPRODUCTION.getCode());
        criteria.addCriterion("orderStatus", Operator.EQ,EquipmentEnums.UpkeepStatus.START.getCode());
        List<EquipmentUpkeepTask> list = equipmentUpkeepTaskService.list(EquipmentUpkeepTask.class, criteria);
        for (EquipmentUpkeepTask task : list) {
            equipmentUpkeepTaskService.updateOccupy(task);
        }
        return Result.OK();
    }

    @PutMapping ("updateTime")
    @Operation(summary = "根据接收字段修改状态", description = "根据接收字段修改状态", method = "PUT")
    public Result<EquipmentUpkeepTask> updateTime(@RequestBody EquipmentUpkeepTask equipmentUpkeepTask){
        return equipmentUpkeepTaskService.updateTime(equipmentUpkeepTask, EquipmentEnums.PmisHode.PRODUCTIONSCHEDULED);
    }
}
